﻿using System;
using System.Collections.Generic;
using System.CodeDom.Compiler;

namespace SWF
{
    public class Push : IAction, IStackManipulator
    {
        public ActionKind ActionId { get { return ActionKind.Push; } }
        public uint Version { get { return 4; } }
        public uint Length
        {
            get
            {
                uint len = 3;
                foreach (IPrimitive p in Values)
                {
                    len += (uint)p.Length;
                }
                return len;
            }
        }

        public uint StackPops { get { return 0; } }
        public uint StackPushes { get { return (uint)Values.Count; } }
        public int StackChange { get { return Values.Count; } }

        public PrimitiveType PrimitiveType;
        public List<IPrimitive> Values = new List<IPrimitive>();

        public Push(SwfReader r, uint maxLen)
        {
            PrimitiveType type;
            while (r.Position < maxLen)
            {
                type = (PrimitiveType)(r.GetByte());
                switch (type)
                {
                    case PrimitiveType.String:
                    {
                        Values.Add(new PrimitiveString(r));
                        break;
                    }
                    case PrimitiveType.Float:
                    {
                        Values.Add(new PrimitiveFloat(r));
                        break;
                    }
                    case PrimitiveType.Null:
                    {
                        Values.Add(new PrimitiveNull(r));
                        break;
                    }
                    case PrimitiveType.Register:
                    {
                        Values.Add(new PrimitiveRegister(r));
                        break;
                    }
                    case PrimitiveType.Boolean:
                    {
                        Values.Add(new PrimitiveBoolean(r));
                        break;
                    }
                    case PrimitiveType.Double:
                    {
                        Values.Add(new PrimitiveDouble(r));
                        break;
                    }
                    case PrimitiveType.Integer:
                    {
                        Values.Add(new PrimitiveInteger(r));
                        break;
                    }
                    case PrimitiveType.Constant8:
                    {
                        Values.Add(new PrimitiveConstant8(r));
                        break;
                    }
                    case PrimitiveType.Constant16:
                    {
                        Values.Add(new PrimitiveConstant16(r));
                        break;
                    }
                    case PrimitiveType.Undefined:
                    {
                        Values.Add(new PrimitiveUndefined(r));
                        break;
                    }
                }
            }
        }

        public void Execute(Runtime.Clip clip, Stack<object> stack, Dictionary<string, object> variables, List<string> constantPool, Dictionary<string, List<IAction>> functionmap)
        {
            foreach (IPrimitive p in Values)
            {
                if (p.PrimitiveType == PrimitiveType.Constant8 || p.PrimitiveType == PrimitiveType.Constant16) stack.Push(constantPool[(int)((uint)p.Value)]);
                else stack.Push(p.Value);
            }
        }
    }
}
